package com.voice.core.connection.callback;

import com.voice.core.entity.HttpHeader;
import com.voice.core.connection.Connection;
import com.voice.core.connection.entity.Stream;
import com.voice.core.connection.entity.StreamData;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.concurrent.CompletableFuture;

@Slf4j
public abstract class AbstractStreamListener<T extends Connection> implements StreamListener<T>{

    private StreamData getStreamData(Stream stream){
        StreamData streamData = stream.getStreamData();
        if (streamData == null) {
            streamData = new StreamData();
            stream.setStreamData(streamData);
        }
        return streamData;
    }

    @Override
    public void onDataRead(T connection, Stream stream, byte[] bytes, boolean endOfStream) {
        StreamData streamData = getStreamData(stream);
        if (streamData == null) {
            this.onStreamError(connection, stream, new IOException(this.toString() + " received data frame on " + stream + ", but headers hasn't received"));
        } else {
            streamData.addData(bytes);
            if (endOfStream) {
                CompletableFuture.runAsync(()->{
                    try {
                        this.onDataRead(connection, stream, streamData);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                });
                stream.close();
            }
        }
    }

    @Override
    public void onHeadersRead(T connection, Stream stream, HttpHeader requestHeader, boolean endOfStream) {
        StreamData streamData = getStreamData(stream);
        streamData.addHeaders(requestHeader);
        if (endOfStream) {
            this.onDataRead(connection, stream, streamData);
            stream.close();
        }
    }

    @Override
    public void onStreamRead(T connection, byte[] bytes) {
        log.info("receive stream data, {}}",bytes);
    }

    @Override
    public void onStreamError(T connection, Stream stream, IOException exception) {
        log.error("receive data error, streamId {}, error {}", stream.getStreamId(), exception.getMessage());
    }

    public abstract void onDataRead(T connection, Stream stream, StreamData streamData);
}
